<template>
  <a-layout class="layout" id="curd-layout">
    <div style="position:fixed;z-index:9999999;bottom:50px;left: 50px">
      <a-drawer
          class="database-drawer"
          title="数据库"
          :width="300"
          :mask="false"
          placement="left"
          v-model:visible="databaseDrawerVisible"
      >
        <database :method="curdMethod" v-model:visible="databaseDrawerVisible"></database>
      </a-drawer>
      <a-tooltip title="数据库" v-if="!databaseDrawerVisible">
        <a-button shape="circle" @click.stop="databaseDrawerVisible = true">
          <template #icon><database-filled /></template>
        </a-button>
      </a-tooltip>
    </div>
    <a-layout-sider :width="130" class="controller ex_scrollbar">
      <a-dropdown :trigger="['contextmenu']" @visibleChange="controllerFormVisible">
        <template #overlay>
          <a-menu>
            <a-menu-item>
              <render :data="controllerForm">
                <PlusOutlined/> 添加
              </render>
            </a-menu-item>
            <a-menu-item v-if="controllerIndex > -1">
              <render :data="controllerEditForm">
                <EditOutlined/> 编辑
              </render>
            </a-menu-item>
            <a-popconfirm title="确认删除？" @confirm="deleteController()" v-if="controllerIndex > -1">
              <template #icon>
                <question-circle-outlined style="color: red"/>
              </template>
              <a-menu-item>
                <template #icon>
                  <DeleteOutlined/>
                </template>
                删除
              </a-menu-item>
            </a-popconfirm>
          </a-menu>
        </template>
        <div class="flex-column">
          <div class="title">
            <span>控制器</span>
            <div>
              <render :data="controllerForm" ></render>
              <a-button size="small" shape="circle" @click="getController">
                <template #icon>
                  <ReloadOutlined/>
                </template>
              </a-button>
            </div>
          </div>
          <ul class="flex-1-auto">
            <li v-for="(item,index) in controller" :key="index"
                @contextmenu.prevent="controllerIndex = index"
                @click="controllerIndex = index;getMethod()"
                :class="controllerIndex == index?'active':''">
              <a-tooltip placement="bottom" :mouseEnterDelay="1">
                <template #title>{{ item.title }}</template>
                <div class="name">{{ item.title }}</div>
              </a-tooltip>
              <a-tooltip placement="bottom" :mouseEnterDelay="1">
                <template #title>{{ item.path }}</template>
                <div class="desc">{{ item.name }}</div>
              </a-tooltip>
            </li>
          </ul>
        </div>
      </a-dropdown>
    </a-layout-sider>
    <a-layout-sider :width="130" class="controller ex_scrollbar">
      <a-dropdown :trigger="['contextmenu']" @visibleChange="methodFormVisible">
        <template #overlay>
          <a-menu>
            <a-menu-item v-if="controllerIndex > -1">
              <render :data="methodForm">
                <PlusOutlined/> 添加
              </render>
            </a-menu-item>
            <a-menu-item v-if="methodIndex > -1">
              <render :data="methodEditForm">
                <EditOutlined/> 编辑
              </render>
            </a-menu-item>
            <a-popconfirm title="确认删除？" @confirm="deleteMethod()" v-if="methodIndex > -1">
              <template #icon>
                <question-circle-outlined style="color: red"/>
              </template>
              <a-menu-item>
                <template #icon>
                  <DeleteOutlined/>
                </template>
                删除
              </a-menu-item>
            </a-popconfirm>
          </a-menu>
        </template>
        <div class="flex-column">
          <div class="title">
            <span>方法</span>
            <div>
              <render :disabled="controllerIndex == -1" :data="methodForm"></render>
              <a-button size="small" shape="circle" @click="getMethod()">
                <template #icon>
                  <ReloadOutlined/>
                </template>
              </a-button>
            </div>
          </div>
          <ul class="flex-1-auto">
            <li v-for="(item,index) in method" :key="index"
                @contextmenu.prevent="methodIndex = index"
                @click="getRender(index)"
                :class="methodIndex == index?'active':''">
              <a-tooltip placement="bottom" :mouseEnterDelay="1">
                <template #title>{{ item.title }}</template>
                <div class="name">{{ item.title }}</div>
              </a-tooltip>

              <a-tooltip placement="bottom" :mouseEnterDelay="1">
                <template #title>{{ item.name }}</template>
                <div class="desc">{{ item.name }}</div>
              </a-tooltip>
            </li>
          </ul>
        </div>
      </a-dropdown>
    </a-layout-sider>
    <a-layout-sider :width="300" class="ex_scrollbar" ref="dragRef">
      <a-tabs type="card" class="curd-tabs">
        <a-tab-pane key="2" tab="表单设计" forceRender>
          <div v-for="group in componentList" class="components">
            <div style="display: flex;align-items: center;margin: 5px">
              <i class="fas fa-layer-group"></i>
              <div style="margin-left: 5px">{{ group.label }}</div>
            </div>
            <div class="components-draggable">
               <draggable :list="group.options" :sort="false"
                          :clone="onClone"
                          @end="onEnd"
                          :move="onCloneMove"
                          chosen-class="chosen-class"
                          :group="{name:'components',pull:'clone',put:false}">
                 <template #item="{element}">
                   <div class="components-item">
                     <div class="components-body">
                       <!--              <render :data="element.component"></render>-->
                       <i :class="element.icon"/> {{ element.label }}
                     </div>
                   </div>
                 </template>
               </draggable>
            </div>
          </div>
        </a-tab-pane>
      </a-tabs>
    </a-layout-sider>
    <a-layout-content class="main">
      <div class="header">
        <div v-if="methodIndex > -1" >
          <a-button @click="dragSave(false)"><span :style="!isSave?'color: red;':''">保存</span>(ctrl+s)</a-button>
          <a-button @click="dragSave(true)">预览代码</a-button>
          <code-diff :code="previewCode" :method="curdMethod"></code-diff>
        </div>
        <div>
          <a-button shape="circle" size="small" @click="getRender(methodIndex)">
            <template #icon>
              <reload-outlined />
            </template>
          </a-button>
          <render :data="$attrs.setting"></render>
        </div>

      </div>
      <div class="drawing ex_scrollbar" ref="drawingRef">
        <render :ref="ref=>setRef(ref)" :data="drawingMain.component" ></render>
      </div>
    </a-layout-content>
    <div class="collapse" @click="settingFormVisible = !settingFormVisible">
      <i :class="settingFormVisible?'fas fa-angle-double-right':'fas fa-angle-double-left'"></i>
    </div>
    <a-layout-sider v-if="settingFormVisible" :width="360" class="settingForm ex_scrollbar">
      <a-tabs type="card" class="curd-tabs">
        <a-tab-pane v-if="settingForm" key="1" tab="组件属性">
          <render :data="settingForm" @watchModel="watchModel"></render>
        </a-tab-pane>
        <a-tab-pane key="2" tab="属性" forceRender>
          <render v-if="drawingMain.component" :data="drawingMain.component.attribute.drawingForm" @watchModel="watchModel"></render>
        </a-tab-pane>
      </a-tabs>

    </a-layout-sider>
    <div style="display: none">
      <render v-for="item in settingFormList" :data="item" @watchModel="watchModel"></render>
    </div>
  </a-layout>
</template>
<script>
import {setObjectValue, exceptField, randomCoding} from "@/utils/index"
import {debounce,cloneDeep} from 'lodash'
import request from '@/utils/axios'
import {toRefs, defineComponent,  onBeforeUnmount, ref, reactive, nextTick, toRaw,onMounted} from "vue"
import {message} from "ant-design-vue";
import draggable from 'vuedraggable'
import {useInjectRenderContext} from "@/components/render/context";
import database from './database.vue'
import CodeDiff from "./codeDiff.vue";
export default defineComponent({
  name: "ExCurd",
  components:{
    CodeDiff,
    draggable,
    database,
  },
  setup(props,ctx) {
    const context = useInjectRenderContext()
    const state = reactive({
      previewCode:{
        old:'',
        new:''
      },
      searchTable:'',
      controller: [],
      controllerIndex: -1,
      method: [],
      methodIndex: -1,
      drawingMain: {
        component: null,
        ref: null,
      },
      componentList: [],
      controllerForm: null,
      controllerEditForm: null,
      methodForm: null,
      saveConfig: {},
      methodEditForm: null,
      settingForm: null,
      settingFormList: [],
      databaseDrawerVisible: false,
      settingFormVisible: true,
      index: -1,
      isSave: true,
      methodTypes: [
        {
          value: 'grid',
          label: '数据表格(grid)',
        },
        {
          value: 'form',
          label: '表单(form)',
        },
        {
          value: 'detail',
          label: '详情(detail)',
        }
      ]
    })

    const dragRef = ref()
    const drawingRef = ref()
    init()
    addEventListener('keydown', keydownEvent)
    addEventListener('keyup', keyupEvent)
    // addEventListener('click',databaseVisableClick)
    onBeforeUnmount(() => {
      removeEventListener('keydown', keydownEvent)
      removeEventListener('keyup', keyupEvent)
      // removeEventListener('click', databaseVisableClick)
    })
    function databaseVisableClick(e){
      const drawerEL = document.getElementsByClassName('database-drawer')[0]
      if(drawerEL && !drawerEL.contains(e.target) && document.getElementById('curd-layout').contains(e.target)){
        state.databaseDrawerVisible = false
      }
    }
    let keyCode1 = 0
    let keyCode2 = 0

    function keydownEvent(e) {
      if (e.keyCode == 17) {
        keyCode1 = 1
      }
      if (e.keyCode == 83) {
        keyCode2 = 1
      }
      if (keyCode1 == 1 && keyCode2 == 1) {
        dragSave()
      }
    }

    function keyupEvent(e) {
      if (e.keyCode == 17) {
        keyCode1 = 0
      }
      if (e.keyCode == 83) {
        keyCode2 = 0
      }
    }

    function watchModel() {
      updateRender()
    }
    function init() {
      getController()
      request('ex-admin/plugin-curd-controller-Index/getFormComponent').then(res => {
        state.componentList = res.data
        state.componentList.forEach(row=>{
          row.options.forEach(item=>{
            request('ex-admin/plugin-curd-controller-Index/getComponent?type='+item.name).then(result => {
              item.component = result.data
            })
          })
        })
      })
    }
    function draggableRender(data) {
      if(['ExForm','ARow','ACol','ExFormMany','ATabPane'].indexOf(data.name) >-1 && !data.content.default){
        data.content.default = []
      }
      for (let slot in data.content) {
        let content = data.content
        let slots = []
        content[slot].forEach(item => {
          slots.push(item)
          draggableRender(item)
        })
        if(['ExForm','ARow','ACol','ExFormMany','ATabPane'].indexOf(data.name) >-1){
          if(slot == 'default'){
            data.content[slot] = draggableComponentRender(data.name,slots,data)
          }else{
            data.content[slot] = slots
          }
        }
      }
    }
    function onCloneMove(e){
      return onMove(e,true)
    }
    function onMove(e,clone = false){
      let element
      if(clone){
        element = e.draggedContext.element.component.name
      }else{
        element = e.draggedContext.element.name
      }

      if(element == 'ACol' && e.relatedContext.component.$attrs.group.name != 'ARow'){
        return false
      }
      if(element != 'ACol' && e.relatedContext.component.$attrs.group.name == 'ARow'){
        return false
      }
      return true
    }
    function getDrawingForm(data,name){
      data.forEach(item=>{
        if (typeof(item) == 'object') {
          if(item.attribute.drawingFormKey){
            request({
              url:'ex-admin/plugin-curd-controller-Index/getDrawingForm',
              method:'post',
              data:{
                key:item.attribute.drawingFormKey
              }
            }).then(res=>{
              item.attribute.drawingForm = JSON.parse(res.data)

            })
          }
          if(item.content){
            for (let slot in item.content){
              getDrawingForm(item.content[slot],name)
            }
          }
        }
      })
    }
    function draggableComponentRender(name,slots,renderData = {}){
      let className = 'ex-drag-container'
      if(name == 'ARow'){
        className += ' curd-children-row'
      }else if(name == 'ACol'){
        className += ' curd-row-draggable'
      }
      getDrawingForm(slots)

      return [{
        name:'DraggableRender',
        attribute:{
          group:{name:name,put:true,pull:true},
          animation:1000,
          chosenClass:'ex-drag-choose',
          list:slots,
          tag:name == 'ARow' ?'render':'div',
          componentData:{data:renderData},
          class:className,
          style:{width:'100%',minHeight:'32px'},
          move:e=>onMove(e)
        },
        event:{
          'End':e=>{
            onEnd(e)
          },
          'Sort':e=>{
            state.drawingMain.ref.forceUpdate()
          },
          'Choose':e=>{
            document.querySelectorAll('[data-choose]').forEach(item=>{
              item.removeAttribute('data-choose')
            })
            e.item.setAttribute('data-choose',true)

            let data = e.item.__draggable_context.element

            if (data.name === 'AFormItem') {
              state.settingForm = data.content.default[0].attribute.drawingForm
            }else if(data.name == 'DraggableRender'){
              state.settingForm = data.attribute.componentData.data.attribute.drawingForm
            }else {
              state.settingForm = data.attribute.drawingForm
            }
          },
        }
      }]
    }
    const updateRender = debounce(updateRenderFunction, 150)
    function updateFormItem(slots,formConfig,setting,formModel,component,field,modelValue){

      slots.forEach(row => {
        if(row.name == 'AFormItem'){
          if (row.attribute && row.attribute.name.indexOf('default') > -1) {
            let val = formConfig[row.content.default[0].bindAttribute.value.replace(formModel + '.', '')]
            if(val === undefined){
              val = formConfig[setting[field]]
            }
            formConfig[setting[field]] = val
            setting.default = formConfig[setting[field]]
            row.content.default[0].bindAttribute.value = modelValue
            row.content.default[0].modelBind.value = modelValue
          } else if (component.name === 'ARangePicker' && row.attribute.title === "默认值") {
            formConfig[setting[field]] = formConfig[row.content.default[0].bindAttribute.value.replace(formModel + '.', '')]
            setting.default = formConfig[setting[field]]
            row.content.default[0].bindAttribute.value = modelValue
            row.content.default[0].modelBind.value = modelValue
            const startField = component.attribute.startField
            component.attribute.startField = formModel + '.' + startField.substr(startField.indexOf('.') + 1)
            const endField = component.attribute.endField
            component.attribute.endField = formModel + '.' + endField.substr(endField.indexOf('.') + 1)
          }
        }else if(row.content && row.content.default){
          updateFormItem(row.content.default,formConfig,setting,formModel,component,field,modelValue)
        }
      })
    }
    function updateDrawingFormRender(slots,name = null){
        slots.forEach(item=>{
          if (typeof(item) == 'object'){
            if(item.name == 'AFormItem'){
              //form
              const drawingComponent = state.drawingMain.component
              const formModel = drawingComponent.bindAttribute.model
              const formConfig = drawingComponent.bind[formModel]
              let formItem = item
              let component = formItem.content.default[0]
              let drawingForm = component.attribute.drawingForm
              let setting = drawingForm.bind[drawingForm.bindAttribute.model]
              for (let field in setting) {
                if (field == 'title' && component.name != 'ExFormMany') {

                  formItem.attribute.label = setting[field]
                } else if (['name', 'default'].indexOf(field) > -1) {

                } else if (field == 'required') {
                  formItem.attribute.required = setting[field]
                } else if (field == 'field' && component.name != 'ACascader') {

                  let modelValue = formModel + '.' + setting[field]
                  if(name == 'ExFormMany'){
                    modelValue = setting[field]
                  }
                  component.bindAttribute[setting.modelValue] = modelValue
                  component.modelBind[setting.modelValue] = modelValue
                  formItem.attribute.name = [setting[field]]
                  if(component.name == 'ExFormMany' && formConfig[setting[field]] === undefined){
                    formConfig[setting[field]] = setting.default
                  }
                  updateFormItem(drawingForm.content.default,formConfig,setting,formModel,component,field,modelValue)
                } else if (['character', 'addonBefore', 'addonAfter', 'prefix', 'suffix'].indexOf(field) > -1 && setting[field]) {
                  let content = toRaw(setting[field])
                  if (Array.isArray(content)) {
                    component.content[field] = content
                  } else {
                    component.content[field] = [content]
                  }
                } else if (field === 'config') {
                  for (let key in setting[field]) {
                    if (key == 'options' && setting[field].options_type == 3) {
                      component.attribute.options = []
                      Object.assign(component.attribute.options, setting[field][key])
                    }
                  }
                  if (component.name == 'ExSelectTable') {
                    let gridUrl = "ex-admin/" + setting[field].grid_class.replaceAll("\\", "-") + "/" + setting[field].grid_method
                    let params = {}
                    if(setting[field].params){
                      setting[field].params.forEach(p => {
                        params[p.var] = p.value
                      })
                    }

                    setObjectValue(component.attribute, 'gridUrl', gridUrl)
                    setObjectValue(component.attribute, 'params', params)
                  }
                } else {
                  setObjectValue(component.attribute, field, setting[field])
                }
              }
            }
            else if(item.name == 'DraggableRender'){
              item.attribute.key = randomCoding(20)
              updateDrawingFormRender(item.attribute.list,item.attribute.group.name)
            }else if(item.name == 'ARow' || item.name == 'ACol'){
              let drawingForm = item.attribute.drawingForm
              let setting = drawingForm.bind[drawingForm.bindAttribute.model]
              delete item.attribute.md
              delete item.attribute.sm
              delete item.attribute.xs
              for (let field in setting) {
                setObjectValue(item.attribute, field, setting[field])
              }
            }else if(item.name == 'ATabs'){
              let drawingForm = item.attribute.drawingForm
              let setting = drawingForm.bind[drawingForm.bindAttribute.model]
              let panes = []
              let initPane
              setting.pane.forEach((row,index)=>{
                let pane = cloneDeep(item.content.default[index])
                if(pane){
                  initPane = pane
                }else{
                  let slot = []
                  pane = cloneDeep(initPane)
                  pane.attribute.key = index+1
                  pane.content = {
                    default:draggableComponentRender('ATabPane',slot)
                  }
                }
                pane.attribute.tab = row.title
                panes.push(pane)
                for (let field in setting) {
                  setObjectValue(item.attribute, field, setting[field])
                }
              })
              item.content.default = panes
              let modelValue = drawingForm.bindAttribute.model + '.' + setting.modelValue
              item.bindAttribute.activeKey  = modelValue
              item.modelBind.activeKey = modelValue
            }else if(item.name == 'ADivider'){
              let drawingForm = item.attribute.drawingForm
              let setting = drawingForm.bind[drawingForm.bindAttribute.model]
              for (let field in setting) {
                if(field == 'title'){
                  item.content = {
                    default:[setting[field]]
                  }
                }else{
                  setObjectValue(item.attribute, field, setting[field])
                }

              }
            }
            if(item.content && item.content.default){
              updateDrawingFormRender(item.content.default)
            }
          }
        })
    }
    //更新绘图
    function updateRenderFunction() {
      const drawingComponent = state.drawingMain.component
      let drawingForm = drawingComponent.attribute.drawingForm
      let setting = drawingForm.bind[drawingForm.bindAttribute.model]
      if (drawingComponent.name == 'ExForm') {

        Object.assign(drawingComponent.attribute, setting)
        if (!drawingComponent.content.default) {
          drawingComponent.content.default = []
        }
        updateDrawingFormRender(drawingComponent.content.default)
      } else if (drawingComponent.name == 'ExGrid') {
        const columns = []
        for (let field in setting) {
          if (field == 'columns') {
            setting[field].forEach(column => {
              columns.push({
                dataIndex: column.field,
                title: column.label,
                type: column.form_type || '',
                header: {
                  name: 'html',
                  attribute: {
                    class: "ex_admin_table_th_name",
                    'data-tag': "span",
                  },
                  content: {
                    default: [column.label]
                  },
                }
              })

            })
            if (setting.switch.indexOf('hideAction') == -1) {
              columns.push({
                dataIndex: 'ExAdminAction',
                title: '',
                header: {
                  name: 'html',
                  attribute: {
                    class: "ex_admin_table_th_name",
                    'data-tag': "span",
                  },
                  content: {
                    default: ['']
                  },
                }
              })
            }
            drawingComponent.attribute.columns = columns
          } else if (field == 'switch') {
            setting.swtichOptions.forEach(attr => {
              drawingComponent.attribute[attr] = setting[field].indexOf(attr) > -1
            })
          } else {
            drawingComponent.attribute[field] = setting[field]
          }
        }
      } else if (drawingComponent.name == 'ADescriptions') {
        for (let field in setting) {
          if (field == 'items') {
            const items = []
            setting[field].forEach(item => {
              items.push({
                name: "ADescriptionsItem",
                attribute: {
                  title: item.label,
                  span: item.span,
                },
                content: {
                  default: [drawingComponent.attribute.data[item.field] ?? '--'],
                  label: [item.label],
                },
              })
            })
            drawingComponent.content.default = items
          } else {
            drawingComponent.attribute[field] = setting[field]
          }
        }
      }
      state.drawingMain.ref.forceUpdate()
      state.isSave = false
    }
    function dragFormSave(slots,components){
      slots.forEach(item=>{
        let itemConfig
        if (typeof(item) == 'object'){
          if(item.name == 'AFormItem'){
            const drawingComponent = state.drawingMain.component
            let component = item.content.default[0].attribute.drawingForm
            state.settingFormList.push(component)
            let field = component.bindAttribute.model
            exceptField(component.bind[field], component.attribute.exceptField || [])
            const formModel = drawingComponent.bindAttribute.model
            const formConfig = drawingComponent.bind[formModel]
            component.bind[field].default = formConfig[component.bind[field].field]
            components.push(component.bind[field])
            itemConfig = component.bind[field]
          }else if(item.name == 'DraggableRender'){
            dragFormSave(item.attribute.list,components)
          }else if(['ARow','ACol','ExFormMany','ATabs','ATabPane','ADivider'].indexOf(item.name) > -1){
            let component = item.attribute.drawingForm
            let field = component.bindAttribute.model
            exceptField(component.bind[field], component.attribute.exceptField || [])
            components.push(component.bind[field])
            itemConfig = component.bind[field]

          }
          if(item.content && item.content.default && itemConfig){
            itemConfig.content = []
            dragFormSave(item.content.default,itemConfig.content)
          }
        }
      })
    }
    function dragSave(preview=false) {

      if(preview) {
        state.previewVisible = false
      }
      state.settingFormList = []
      updateRender()
      setTimeout(()=>{
        state.saveConfig = {}
        const drawingComponent = state.drawingMain.component
        let field = drawingComponent.attribute.drawingForm.bindAttribute.model
        state.saveConfig.config = drawingComponent.attribute.drawingForm.bind[field]
        if (drawingComponent.name == 'ExForm') {
          state.saveConfig.type = 'form';
          state.saveConfig.component = []
          dragFormSave(drawingComponent.content.default,state.saveConfig.component)
          let validateNum = 0
          nextTick(()=>{

            state.settingFormList.forEach(item=>{
              context[item.bindAttribute.ref].form.validate().then(()=>{
                validateNum++
                if(validateNum == state.settingFormList.length){
                  saveRequest(preview)
                }
              }).catch(error=>{
                if(error.errorFields.length === 0){
                  validateNum++
                  if(validateNum == state.settingFormList.length){
                    saveRequest(preview)
                  }
                }
                error.errorFields.forEach(errorField=>{
                  let title = `【${error.values.title}】` || '【】'
                  message.error(title + errorField.errors[0])
                  state.settingFormList = []
                })
              })
            })

          })
        } else if (drawingComponent.name == 'ExGrid') {
          state.saveConfig.type = 'grid';
          saveRequest(preview)
        } else if (drawingComponent.name == 'ADescriptions') {
          state.saveConfig.type = 'detail';
          saveRequest(preview)
        }

      },500)
    }
    function getHistory(page,size){
      return new Promise((resolve) =>{
        request({
          url: 'ex-admin/plugin-curd-controller-Index/getHistory',
          method: 'post',
          data: {
            class: state.controller[state.controllerIndex].class,
            method: state.method[state.methodIndex].name,
            page: page,
            size: size,
          }
        }).then(res=>{
          resolve(res.data)
        })
      })

    }
    function saveCodeRequest(code){
      return new Promise((resolve) =>{
        request({
          url: 'ex-admin/plugin-curd-controller-Index/saveCode',
          method: 'post',
          data: {
            id: state.method[state.methodIndex].id,
            controller: state.controller[state.controllerIndex].name,
            class: state.controller[state.controllerIndex].class,
            function: state.method[state.methodIndex].name,
            setting: state.saveConfig,
            code:code
          }
        }).then(res => {
          state.settingFormList = []
          getRender(state.methodIndex)
          state.isSave = true
          resolve()
        })
      })

    }
    function saveRequest(preview){
      request({
        url: 'ex-admin/plugin-curd-controller-Index/'+(preview?'preview':'save'),
        method: 'post',
        data: {
          id: state.method[state.methodIndex].id,
          controller: state.controller[state.controllerIndex].name,
          class: state.controller[state.controllerIndex].class,
          function: state.method[state.methodIndex].name,
          setting: state.saveConfig
        }
      }).then(res => {
        state.settingFormList = []
        if(preview){
          state.previewCode = res.data
          state.previewVisible = true
        }else{
          getRender(state.methodIndex)
          state.isSave = true
        }
      })
    }
    function setRef(ref) {
      state.drawingMain.ref = ref
    }

    function getController() {
      request('ex-admin/plugin-curd-controller-Index/getController?curd_ref='+ctx.attrs.curd_ref).then(res => {
        state.controller = res.data.list
        state.controllerForm = res.data.controllerForm
      })
    }
    function getMethod() {
      state.methodIndex = -1
      request({
        url: 'ex-admin/plugin-curd-controller-Index/getMethod',
        method: 'post',
        data: {
          curd_ref: ctx.attrs.curd_ref,
          class: state.controller[state.controllerIndex].class,
          controller: state.controller[state.controllerIndex].name,
          table: state.controller[state.controllerIndex].table,
          id:  state.controller[state.controllerIndex].id,
        }
      }).then(res => {
        state.methodForm = res.data.methodForm
        state.method = res.data.list
      })
    }

    function deleteMethod() {
      request({
        url: 'ex-admin/plugin-curd-controller-Index/deleteMethod',
        method: 'post',
        data: {
          class: state.controller[state.controllerIndex].class,
          controller: state.controller[state.controllerIndex].name,
          method: state.method[state.methodIndex].name,
          id: state.method[state.methodIndex].id,
        }
      }).then(res => {
        getMethod()
      })
    }
    function deleteController() {
      const controller = state.controller[state.controllerIndex]
      request({
        url: 'ex-admin/plugin-curd-controller-Index/deleteController',
        method: 'post',
        data: {
          id: controller.id,
          path: controller.path,
        }
      }).then(res => {
        state.controllerIndex = -1
        getController()
        state.method = []
      })
    }

    function getRender(index) {
      state.methodIndex = index
      state.settingForm = null
      request({
        url: 'ex-admin/plugin-curd-controller-Index/render',
        method: 'post',
        data: {
          class: state.controller[state.controllerIndex].class,
          function: state.method[state.methodIndex].name,
          var: []
        }
      }).then(res => {
        state.isSave = true
        draggableRender(res.data)
        state.drawingMain.component = res.data
      })
    }



    function onClone(data){
      if(!data.component){
        return undefined
      }
      let component = cloneDeep(data.component)
      if(component.name == 'AFormItem'){

        let drawingForm = component.content.default[0].attribute.drawingForm
        let setting = drawingForm.bind[drawingForm.bindAttribute.model]
        drawingForm.attribute.key = randomCoding(20)
        if(!setting.field){
          setting.field = randomCoding(20)
        }
        component.attribute.validateFormField = state.drawingMain.component.bindAttribute.validateField
        if(component.content.default[0].name == 'ExFormMany'){
          let slots = []
          component.content.default[0].content = {
            default:draggableComponentRender(component.content.default[0].name,slots,component.content.default[0])
          }

        }
      }
      let slots = []
      if(component.name == 'ARow'){
        let slotsCol = []
        component.content.default[0].content = {
          default:draggableComponentRender('ACol',slotsCol)
        }
        slots = component.content.default
        component.content = {
          default:draggableComponentRender(component.name,slots,component)
        }
      }else if(component.name == 'ACol'){
        component.content = {
          default:draggableComponentRender(component.name,slots,component)
        }
      }else if(component.name == 'ATabs'){

        let pane = component.content.default[0]
        pane.content = {
          default:draggableComponentRender('ATabPane',slots,pane)
        }
        component.content = {
          default:[pane]
        }
      }
      return component
    }
    function onEnd(e){
      if(e.from !== e.to && !e.item._underlying_vm_){
        message.warn('请编辑字段配置属性再进行拖拽')
      }
      updateRenderFunction()
    }
    function controllerFormVisible(visible){
      if(visible){
        const controller = state.controller[state.controllerIndex]
        state.controllerEditForm = cloneDeep(state.controllerForm)
        let params = state.controllerEditForm.content.content[0].attribute.params
        params.id = controller.id
        params.class = controller.class
        params.path = controller.path
        params.title = controller.title
        params.name = controller.name
        params.table = controller.table
      }
    }
    function methodFormVisible(visible){
      if(visible){
        const method = state.method[state.methodIndex]
        state.methodEditForm = cloneDeep(state.methodForm)
        let params = state.methodEditForm.content.content[0].attribute.params
        params.id = method.id
        params.type = method.type
        params.name = method.name
        params.oldName = method.name
        params.oldTitle = method.title
      }

    }
    const curdMethod = {onEnd,onClone,saveCodeRequest,getHistory}
    return {
      curdMethod,
      onMove,
      onCloneMove,
      onEnd,
      onClone,
      getController,
      watchModel,
      dragSave,
      getRender,
      getMethod,
      deleteMethod,
      deleteController,
      controllerFormVisible,
      methodFormVisible,
      dragRef,
      drawingRef,
      setRef,
      ...toRefs(state)
    }
  }
})
</script>


<style scoped lang="scss">
.layout {
  height: 100%;
  background-color: #FFF;
}

.components {
  padding: 10px;
}

.components-draggable .components-item {
  display: inline-block;
  width: 46%;
  margin: 2%;
  box-shadow: 1px 1px 3px 1px #ccc;
  border-radius: 5px;
}

.components-body {
  padding: 8px 10px;
  font-size: 12px;
  cursor: move;
  border-radius: 3px;
}
.components-body:hover{
  cursor: move;
  border: 1px dashed var(--ant-primary-color);
}

.drawing {
  position: relative;
  flex: 1;
}


.main {
  border: 1px solid #f1e8e8;
  border-top: none;
  border-bottom: none;
  display: flex;
  flex-direction: column;

  .header {
    margin:0 10px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-bottom: 1px solid #f1e8e8;
  }
}

.controller {
  height: 100%;

  .title {
    padding: 5px 0;
    display: flex;
    justify-content: space-between;
    margin: 0 10px;
    align-items: center;
    text-align: center;
    border-bottom: 1px solid #f1e8e8;
    font-size: 16px;
  }

  ul {
    border-right: 1px solid #f1e8e8;
    height: 100%;
    padding: 0px;
    margin: 0px;
    list-style: none;

  }

  .active {
    cursor: pointer;
    background: var(--ant-primary-color);
    color: #f0f0f0;

    .desc {
      color: #f0f0f0;
    }
  }

  li {
    padding: 10px 0;
    text-overflow: ellipsis;
    text-indent: 15px;

    &:hover {
      cursor: pointer;
      background: var(--ant-primary-color);
      color: #f0f0f0;

      .desc {
        color: #f0f0f0;
      }
    }

    .name {
      text-overflow: ellipsis;
      overflow: hidden;


    }

    .desc {
      font-size: 12px;
      color: #00000073;
      text-overflow: ellipsis;
      overflow: hidden;
    }
  }
}

.right {

  :deep(.ant-tabs-nav-list) {
    width: 100%;
  }

  :deep(.ant-tabs-tab) {
    width: 50%;
  }

  :deep(.ant-tabs-tab-btn) {
    margin: 0 auto;
  }
}





.collapse {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0 5px;
  cursor: pointer;
  border-right: 1px solid #f1e8e8;
}

.curd-tabs{
  height: 100%;
}
.curd-tabs :deep(.ant-tabs-content){
  height: 100%;
  overflow-y: auto;
}
.flex-column{
  display: flex;
  flex-direction: column;
  height: 100%
}
.flex-1-auto{
  flex: 1;
  overflow-y: auto;
}
:deep(:root){
  --code-font-size: 12px !important;
}
</style>
